package com.bjy.qa.controller.user;

import com.bjy.qa.dao.user.UserRoleDao;
import com.bjy.qa.entity.MyPage;
import com.bjy.qa.entity.Response;
import com.bjy.qa.entity.ResponsePagingData;
import com.bjy.qa.entity.user.User;
import com.bjy.qa.entity.user.UserResponse;
import com.bjy.qa.entity.user.UserRole;
import com.bjy.qa.enumtype.ErrorCode;
import com.bjy.qa.service.user.IUserCompanyProjectService;
import com.bjy.qa.service.user.IUserService;
import com.bjy.qa.util.security.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user/user")
@Validated
@Api(tags = "用户管理")
public class UserController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    IUserService iUserService;

    @Resource
    UserRoleDao userRoleDao;

    @Resource
    IUserCompanyProjectService iUserCompanyProjectService;

    @RequestMapping(value = "/login", method = {RequestMethod.POST})
    @ResponseBody
    @Validated(User.UserLoingGroup.class)
    @ApiOperation(value = "用户登录", notes = "用户登录接口")
    public Response<UserResponse> login(@RequestBody @Valid User user) {
        logger.info("{}", user);
        Response response = Response.success(iUserService.login(user));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/getInfo", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "得到当前登录用户信息", notes = "得到当前登录用户信息")
    public Response<User> getInfo() throws Exception {
        logger.info("得到当前登录用户信息，userId: " + SecurityUtils.getCurrentUserId());
        User user = (User) iUserService.selectWholeInfoById(SecurityUtils.getCurrentUserId());

        // 设置用户角色
        LinkedList roles = new LinkedList();
        List<UserRole> userRoles = userRoleDao.selectByUserId(user.getId());
        for (UserRole userRole : userRoles) {
            roles.add(userRole.getRole().getName());
        }
        user.setRoles(roles);

        Response response = Response.success(user);
        logger.info("得到当前登录用户信息，成功。{}", response);
        return response;
    }

    /**
     * 查询用户完整信息，包括公司及项目列表（需要关联多个表一般不要使用）
     * @param user 用户信息
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/selectWholeInfoById", method = {RequestMethod.POST})
    @ResponseBody
    @Validated(User.IdGroup.class)
    @ApiOperation(value = "根据用户 ID 查询用户信息", notes = "根据用户 ID 查询用户信息")
    public Response<User> findByid(@RequestBody @Valid User user) throws Exception {
        logger.info("userId: " + user.getId());
        Response response = Response.success(iUserService.selectWholeInfoById(user.getId()));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/add", method = {RequestMethod.POST})
    @ResponseBody
    @Validated(User.UserAddGroup.class)
    @ApiOperation(value = "添加用户", notes = "添加用户")
    public Response<Integer> add(@RequestBody @Valid User user) throws Exception {
        logger.info("{}", user);
        Response response = Response.success(iUserService.add(user));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/update", method = {RequestMethod.POST})
    @ResponseBody
    @Validated(User.UserUpdateGroup.class)
    @ApiOperation(value = "修改用户信息", notes = "修改用户信息")
    public Response<Integer> update(@RequestBody @Valid User user) throws Exception {
        logger.info("修改用户信息 {}", user);
        Response response = Response.success(iUserService.update(user));
        logger.info("修改用户信息，成功 {}", response);
        return response;
    }

    @RequestMapping(value = "/updateCurrentCompanyProject", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "更新用户当前选中的公司和项目", notes = "更新用户当前选中公司和项目")
    public Response<Integer> updateCurrentCompanyProject(@RequestBody User user) throws Exception {
        user.setId(SecurityUtils.getCurrentUserId());
        logger.info("更新用户当前选中的公司和项目 {}", user);

        Response response;
        if (!iUserCompanyProjectService.hasUserProjectPermissions(user.getCompanyId(), user.getProjectId())) {
            response = Response.fail(ErrorCode.UNAUTHORIZED, "您选择的 公司 或 项目 不存在，或者您没有权限，请刷新页面后重试！");
        } else {
            response = Response.success(iUserService.updateCurrentCompanyProject(user));
        }

        logger.info("更新用户当前选中的公司和项目，成功。{}", response);
        return response;
    }

    @RequestMapping(value = "/locking", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "锁定用户", notes = "锁定用户")
    public Response<Integer> locking(@RequestBody User user) throws Exception {
        logger.info("{}", user);
        Response response = Response.success(iUserService.locking(user));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/changeCode", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "修改用户密码", notes = "修改用户密码")
    public Response<Boolean> changeCode(@RequestBody User user) {
        logger.info("修改用户密码 {}", user);
        Response response = Response.success(iUserService.changeCode(user));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/logout", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "用户退出", notes = "用户退出")
    public String logout() throws Exception {
        // TODO: 2022/6/4 临时写的没有完成资源释放
        // todo 退出登录，清除 redis 中该用户的缓存
        return "{\"code\":0,\"data\":{}}";
    }

    @RequestMapping(value = "/list", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "分页查询用户列表", notes = "分页查询用户列表")
    public Response<ResponsePagingData> list(@RequestBody MyPage<User> myPage) {
        logger.info("{}", myPage);
        Response response = Response.success(iUserService.list(myPage));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/listByProjectId", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "按 项目 ID 分页查询用户列表", notes = "按 项目 ID 分页查询用户列表")
    public Response<ResponsePagingData> listByProjectId(@RequestBody MyPage<User> myPage) {
        logger.info("{}", myPage);
        Response response = Response.success(iUserService.listByProjectId(myPage));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/selectUserByProjectId", method = {RequestMethod.GET})
    @ResponseBody
    @ApiOperation(value = "通过 项目 ID 查询所有拥有该项目权限的用户", notes = "通过 项目 ID 查询所有拥有该项目权限的用户")
    public Response<List<User>> selectUserByProjectId(Long id) {
        logger.info("通过 项目 ID 查询所有拥有该项目权限的用户， projectId: {}", id);
        Response response = Response.success(iUserService.selectUserByProjectId(id));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/selectUserByNotIncludeProjectId", method = {RequestMethod.GET})
    @ResponseBody
    @ApiOperation(value = "通过 项目 ID 查询所有不包含该项目权限的用户", notes = "通过 项目 ID 查询所有不包含该项目权限的用户")
    public Response<List<User>> selectUserByNotIncludeProjectId(Long projectId) {
        logger.info("通过 项目 ID 查询所有不包含该项目权限的用户， projectId:{}", projectId);
        Response response = Response.success(iUserService.selectUserByNotIncludeProjectId(projectId));
        logger.info("通过 项目 ID 查询所有不包含该项目权限的用户，成功。{}", response);
        return response;
    }

    @GetMapping("/generateToken")
    @ResponseBody
    @ApiOperation(value = "生成用户对外Token", notes = "生成用户对外Token")
    public Response<String> generateToken(@RequestParam(name = "day") @NotNull(message = "day: 字段必填") int day) throws Exception {
        logger.info("生成用户对外Token，day: " + day);
        User user = SecurityUtils.getCurrentUser();

        // 扩展信息（webhook 对应信息）
        Map<String, Object> extMap = new HashMap<>();
        extMap.put("type", "webhook");
        extMap.put("projectId", user.getProjectId());

        Response response = Response.success(iUserService.generateToken(user, extMap, day));
        logger.info("生成用户对外Token: {}", response);
        return response;
    }

    @GetMapping("/removeUserProject")
    @ResponseBody
    @ApiOperation(value = "将用户从项目中移除", notes = "将用户从项目中移除")
    public Response<Object> removeUserProject(@RequestParam @NotNull(message = "userId: 字段必填") Long userId, @RequestParam @NotNull(message = "projectId: 字段必填") Long projectId) {
        logger.info("将用户从项目中移除，userId: {}, projectId: {}", userId, projectId);
        Response response = Response.success(iUserService.removeUserProject(userId, projectId));
        logger.info("将用户从项目中移除: {}", response);
        return response;
    }
}
